package com.hq.common.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.*;

/**

 * @since 2015-01-18 23:22
 */
public class PropertiesCryptConfigurer extends PropertyPlaceholderConfigurer {

    private static final String JDBC_USERNAME = "jdbc.username";
    private static final String JDBC_PASSWORD = "jdbc.password";
    private static final String JDBC_URL = "jdbc.url";
    protected static final String ENCRPYT_KEY_BUNCH = "abcdefghigklmn123456opqrstuvwxyz";
    protected static final String ENCRPYT_PREFIX = "{SGCC}";
    private Resource location;

    private static String defaultIfEmpty(String str, String defaultStr) {
        return StringUtils.isEmpty(str) ? defaultStr : str;
    }

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        boolean needStore = false;//需要修改配置文件
        String username = props.getProperty(JDBC_USERNAME);
        String usernameEn = username;//加密的用户名
        if (!StringUtils.isEmpty(username)) {
            if (username.startsWith(ENCRPYT_PREFIX)) {//已经加密过
                username = getDecryptedValue(username);
                props.setProperty(JDBC_USERNAME, username);//重新赋值
            } else {//未加密，则加密并更新配置文件
                usernameEn = getEncrpytedValue(username);
                needStore = true;
            }
        }

        String password = props.getProperty(JDBC_PASSWORD);
        String passwordEn = password;
        if (!StringUtils.isEmpty(password)) {
            if (password.startsWith(ENCRPYT_PREFIX)) {//已经加密过
                password = getDecryptedValue(password);
                props.setProperty(JDBC_PASSWORD, password);//重新赋值
            } else {//未加密，则加密并更新配置文件
                passwordEn = getEncrpytedValue(password);
                needStore = true;
            }
        }

        String jdbcUrl = props.getProperty(JDBC_URL);
        String jdbcUrlEn = jdbcUrl;
        if (!StringUtils.isEmpty(jdbcUrl)) {
            if (jdbcUrl.startsWith(ENCRPYT_PREFIX)) {//已经加密过
                jdbcUrl = getDecryptedValue(jdbcUrl);
                props.setProperty(JDBC_URL, jdbcUrl);//重新赋值
            } else {//未加密，则加密并更新配置文件
                jdbcUrlEn = getEncrpytedValue(jdbcUrl);
                needStore = true;
            }
        }

        if (needStore) {
            try {
                Map<String, String> map = new HashMap<String, String>();
                map.put(JDBC_USERNAME, defaultIfEmpty(usernameEn, username));
                map.put(JDBC_PASSWORD, defaultIfEmpty(passwordEn, password));
                map.put(JDBC_URL, defaultIfEmpty(jdbcUrlEn, jdbcUrl));
                storeProperties(map);
            } catch (Exception e) {
                logger.error("保存配置文件异常：" + e.getMessage());
                e.printStackTrace();
            }
        }
        super.processProperties(beanFactoryToProcess, props);
    }

    /**
     * 保存日志配置
     *
     * @param propValues
     */
    protected void storeProperties(Map<String, String> propValues) {
        logger.info("尝试加密数据库连接信息");
        List<String> lineList = new ArrayList<String>();
        try {
            BufferedReader bufReader = new BufferedReader(new InputStreamReader(new FileInputStream(this.location.getFile()), "UTF-8"));
            String line = null;
            while ((line = bufReader.readLine()) != null) {
                line = line.trim();
                for (Map.Entry<String, String> entry : propValues.entrySet()) {
                    if (line.startsWith(entry.getKey())) {
                        line = entry.getKey() + "=" + propValues.get(entry.getKey());
                        break;
                    }
                }
                lineList.add(line);
            }
            bufReader.close();
//            BufferedWriter bufWriter = new BufferedWriter(new FileWriter(this.location.getFile()));
            BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.location.getFile()), "UTF-8"));
            for (String lineStr : lineList) {
                bufWriter.write(lineStr + "\n");
            }
            bufWriter.close();
        } catch (FileNotFoundException e) {
            logger.error("Properties配置文件未找到：" + e.getMessage());
        } catch (IOException e) {
            logger.error("保存Properties配置文件失败：" + e.getMessage());
        }
    }

    /**
     * @param str
     * @return
     */
    private String getEncrpytedValue(String str) {
        String en = str;
        try {
            en = EncrpytUtils.encryptDES(str, ENCRPYT_KEY_BUNCH);
            en = ENCRPYT_PREFIX + en;
        } catch (Exception e) {
            logger.error("加密Properties配置值密文失败：" + e.getMessage());
        }
        return en;
    }

    private String getDecryptedValue(String str) {
        String dec = str;
        try {
            dec = EncrpytUtils.decryptDES(str.replace(ENCRPYT_PREFIX, ""), ENCRPYT_KEY_BUNCH);
        } catch (Exception e) {
            logger.error("解密Properties配置值密文失败：" + e.getMessage());
        }
        return dec;
    }

    public static String decryptPropertyValue(String value) {
        if (value != null && value.length() > 0) {
            if (value.startsWith(ENCRPYT_PREFIX)) {//已经加密过
                try {
                    value = EncrpytUtils.decryptDES(value.replace(ENCRPYT_PREFIX, ""), ENCRPYT_KEY_BUNCH);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return value;
    }

    @Override
    public void setLocation(Resource location) {
        super.setLocation(location);
        this.location = location;
    }

}